package medOffice;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Classe que gera elatorio de contas
 * 
 * @author Jose Amilton Filho - amiltonacioli@ibest.com.br
 * @author Ana Clara Lacerda - anacls@lcc.ufcg.edu.br
 * @version 0.2 - 02/12/2009
 */

public class RelatoriosConsultas {
	
	/**
	 * Metodo que calcula o saldo das consultas que ja se realizaram.
	 * @param List<Consulta>
	 * @return double valor total
	 */
	private static double calculaSaldo(List<Consulta> aCalcular) {
		double saldo = 0;

		for (Consulta cons : aCalcular) {
			if (cons.foiAtendida())
				saldo += cons.getValor();
		}

		return saldo;
	}
	
	/**
	 * Metodo que gera o relatorio organizado numa String 
	 * @param Map<Calendar, List<Consulta>>
	 * @return String do relatorio
	 */
	public static String gerarRelatorioString(
			Map<Calendar, List<Consulta>> mapaMesConsultas) {
		String saida = "";

		for (Calendar mes : mapaMesConsultas.keySet()) {
			saida += "Mes: "
					+ new SimpleDateFormat("MM/yyyy").format(mes.getTime())
					+ emiteRelatorio(mapaMesConsultas.get(mes)) + "\n";
		}

		return saida;

	}
	
	/**
	 * Metodo que calcula o saldo total por plano de saude.
	 * @param PlanoDeSaude plano
	 * @param List<Consulta>
	 * @return String formatada com o saldo total
	 */
	public static String saldoPlanoDeSaude(PlanoDeSaude plano,
			List<Consulta> consultas) {
		List<Consulta> consultasDoPlano = new ArrayList<Consulta>();
		for (Consulta c : consultas) {
			if (c.getPaciente().getPlanoDeSaude().equals(plano))
				consultasDoPlano.add(c);
		}
		if (consultasDoPlano.isEmpty())
			return plano.getNomeDoPlano()
					+ "\nNenhuma consulta foi marcada nesse Plano.";
		return plano.getNomeDoPlano() + emiteRelatorio(consultasDoPlano);
	}
	
	/**
	 * Metodo que emite relatorio das consultas
	 * @param List<Consulta> lista de consultas
	 * @return String formatada.
	 */
	public static String emiteRelatorio(List<Consulta> consultas) {
		return "Saldo: R$ " + String.format("%.2f", calculaSaldo(consultas));
	}
	
	/**
	 * Metodo que gera um relatorio especifico.
	 * @param List<Consulta> consultas
	 * @return String formatada.
	 * @throws Exception lancada quando a consulta for nula
	 */
	public static String geraRelatorioEspecifico(List<Consulta> consultas)
			throws Exception {
		if (consultas == null) {
			throw new Exception("Consultas invalida");
		}
		if (consultas.isEmpty())
			return "Nenhuma Consulta foi atendida";
		String relatorio = "";
		Map<PlanoDeSaude, List<Consulta>> mapa = new HashMap<PlanoDeSaude, List<Consulta>>();
		for (Consulta c : consultas) {
			if (!mapa.containsKey(c.getPaciente().getPlanoDeSaude()))
				mapa.put(c.getPaciente().getPlanoDeSaude(),
						new ArrayList<Consulta>());
			mapa.get(c.getPaciente().getPlanoDeSaude()).add(c);
		}
		for (PlanoDeSaude ps : mapa.keySet()) {
			relatorio += saldoPlanoDeSaude(ps, mapa.get(ps));
			relatorio += "\n";
			relatorio += "Total " + emiteRelatorio(consultas);
		}

		return relatorio;
	}
	
	/**
	 * Metodo que gera relatorio entre duas datas.
	 * @param List<Consulta> consultas
	 * @param Calendar inicio
	 * @param Calendar fim
	 * @return String
	 * @throws Exception lancada caso alguns dos atributos seja nulo.
	 */ 
	public static String geraRelatorioEntreDatas(List<Consulta> consultas,
			Calendar inicio, Calendar fim) throws Exception {
		if (consultas == null || inicio == null || fim == null)
			throw new Exception("Consultas invalida ou datas invalidas");
		List<Consulta> consultasValidas = new ArrayList<Consulta>();
		for (Consulta c : consultas) {
			if (c.getData().before(fim) && c.getData().after(inicio))
				consultasValidas.add(c);
			else if (c.getData().equals(fim) || c.getData().equals(inicio))
				consultasValidas.add(c);
		}
		if (consultasValidas.isEmpty())
			return "Entre "
					+ new SimpleDateFormat("dd/MM/yyyy").format(inicio
							.getTime()) + " e "
					+ new SimpleDateFormat("dd/MM/yyyy").format(fim.getTime())
					+ "\n\n" + "Nenhuma consulta foi atendida entre essas datas";
		return "Entre "
				+ new SimpleDateFormat("dd/MM/yyyy").format(inicio.getTime())
				+ " e "
				+ new SimpleDateFormat("dd/MM/yyyy").format(fim.getTime())
				+ "\n\n" + geraRelatorioEspecifico(consultasValidas);
	}
	
	/**
	 * Metodo que gera relatorio
	 * @param List<Consulta> consultas
	 * @param Calendar data
	 * @return String relatorio
	 * @throws Exception lancado caso a consulta seja nula.
	 */
	public static String geraRelatorioData(List<Consulta> consultas,
			Calendar data) throws Exception {
		if (consultas == null)
			throw new Exception("Consultas invalidas");
		List<Consulta> consultasValidas = new ArrayList<Consulta>();
		for (Consulta c : consultas) {
			if (c.getData().equals(data))
				consultasValidas.add(c);
		}
		if (consultasValidas.isEmpty())
			return "Data: "
					+ new SimpleDateFormat("dd/MM/yyyy").format(data.getTime())
					+ "\n\n" + "Nenhuma consulta foi atendida nesse dia";
		return "Data: "
				+ new SimpleDateFormat("dd/MM/yyyy").format(data.getTime())
				+ "\n\n" + geraRelatorioEspecifico(consultasValidas);
	}
}
